package cn.serein.charging.order.quartz;


import cn.serein.charging.order.dao.repository.OrderRepository;
import cn.serein.charging.order.pojo.po.ChargingBillFailPO;
import cn.serein.charging.order.pojo.po.ChargingBillSuccessPO;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Date;
import java.util.UUID;


/**
 * open-feign和保障服务通信
 1 创建保障服务微服务
 2 创建一个接口, 创建维修单 入参
 3 维修单对应的表
 id 订单信息(订单号),
 设备信息(站id,桩id,枪id)
 维修人员信息(id)
 维修单信息(维修单号, status(新创建,完成,修理中),时间)
4 订单服务增加 保障服务 feignClient
5  open-feign 注入  feignClient 直接调用

rabbitmq消息队列保障服务通信
1 定义保障服务 Exchange 和 queue 并通过Routingkey 绑定
2 定义保障服务Producer 用来给 保障服务 Exchange 发消息
3 消息的格式 {orderNO:"112233",设备信息:{}}
4 创建保障服务微服务
5 创建保障服务微服务queue的消费者 @RabbitListener 监听 保障服务的queue
6 生成维修单

保障服务 都需要考虑 幂等性,保障同一个订单不能搞出多个维修单

生成维修单后,可以让维修师傅来抢单
 */

@Slf4j
public class DeviceCheckJob implements Job {

    // 自动装配
    // 由于OrderRepository 不在IOC 容器中 可以通过applicationContext 获取
//    @Autowired
//    private OrderRepository orderRepository;

    // 无参构造
    public DeviceCheckJob() {
    }


    // 创建定时任务
    public DeviceCheckJob(String orderNo, Integer gunId) throws SchedulerException {
        log.debug("创建定时任务,订单号:{},枪id:{}",orderNo,gunId);
        // 创建调度器工厂
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        // 通过调度器工厂创建调度器
        Scheduler scheduler = schedulerFactory.getScheduler();

        JobDetail jobDetail = JobBuilder.newJob(DeviceCheckJob.class)
                .withIdentity("DeviceCheckJob" + UUID.randomUUID(),"device_check_jobs")
                .usingJobData("orderNo",orderNo)
                .usingJobData("gunId",gunId)
                .build();

        // 定义任务触发时间
        long now = System.currentTimeMillis();

        long deviceCheckTime = 1000 * 60 * 1;

        // 任务触发时间
        Date triggerTime = new Date(now + deviceCheckTime);

        // 触发器
        Trigger trigger = TriggerBuilder.newTrigger().startAt(triggerTime).build();

        // 调度器  将任务和触发器绑定起来
        scheduler.scheduleJob(jobDetail,trigger);
        // 启动调度器
        scheduler.start();
    }


    // 执行  需要干的事
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {

        JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();


        String orderNo = jobDataMap.getString("orderNo");
        Integer gunId = jobDataMap.getInt("gunId");


        OrderRepository orderRepository = DeviceCheckJobUtils
                .getBean("orderRepository",OrderRepository.class);


        //  通过订单号查看是否有成功或者失败订单记录
        ChargingBillSuccessPO chargingBillSuccessPO = orderRepository.getSuccessOrder(orderNo);
        // 如果成功订单记录表中不存在
        if(chargingBillSuccessPO == null){
            // 去失败订单记录表中查看是否存在
            ChargingBillFailPO oldChargingBillFailPO = orderRepository.getFailOrder(orderNo);

            // 如果失败订单记录不存在
            if(oldChargingBillFailPO == null){
                // 未响应  插入失败顶顶那记录
                ChargingBillFailPO newChargingBillFailPO = new ChargingBillFailPO();
                // 设置订单号
                newChargingBillFailPO.setBillId(orderNo);
                // 设置失败描述
                newChargingBillFailPO.setFailDesc("设备自检失败---设备无响应");
                orderRepository.saveFailOrder(newChargingBillFailPO);

                log.debug("调用保障分服务，通知维修人员对设备进行检查和维护，"+
                        "要告诉保障服务设备信息，或者订单号，通过订单号反查设备信息");
            }else{
                //有失败订单记录 无需修改失败原因，真实的原因是 有响应-无法充电 不能改成 无响应
                log.debug("设备自检失败-设备有响应,但是充不了电,请您更换充电设备,这里逻辑无需修改设备的失败原因");
            }



        }else{
            //有成功订单记录
            log.debug("有成功订单记录,表示设备自检成功,有响应,能充电");
            log.debug("更新设备信息到订单成功表,枪id:{},订单编号:{},这里不是必须的操作," +
                    "为了演示,给成功订单表填充设备信息");
            orderRepository.updateDeviceInfo(orderNo,gunId);
            log.debug("更新设备信息到订单成功表成功,枪id:{},订单编号:{},这里不是必须的操作," +
                    "为了演示,给成功订单表填充设备信息");
        }
    }
}
